package com.ruoyi.common.core.xss;

import com.ruoyi.common.core.utils.StringUtils;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 自定义xss校验注解实现
 *
 * @author ruoyi
 */

/**
 * 定义了一个名为XssValidator的类，实现了ConstraintValidator接口，并将Xss注解作为泛型参数。
 * 该类用于验证一个String类型的变量是否存在XSS（跨站脚本攻击）漏洞。
 * ConstraintValidator接口定义了用于验证注解的值是否合法的方法，
 * Xss注解用于标记需要进行XSS验证的字段或方法。在这个类中，
 * 需要实现initialize()和isValid()方法来对String类型的值进行XSS验证。
 */
public class XssValidator implements ConstraintValidator<Xss, String> {
    /**
     * 该正则表达式用于匹配HTML标签，其具体含义如下：
     *
     * - `<`: 匹配左尖括号
     * - `(\\S*?)`: 匹配零个或多个非空白字符，非贪婪模式，即尽可能少地匹配
     * - `[^>]*`: 匹配零个或多个非右尖括号的字符
     * - `>`: 匹配右尖括号
     * - `.*?`: 匹配任意字符，非贪婪模式
     * - `|`: 或者
     * - `<.*? />`: 匹配空格符号的闭合标签
     *
     * 整体上，该正则表达式可以匹配包含在尖括号中的HTML标签，包括有属性的标签和自闭合标签。
     */
    private static final String HTML_PATTERN = "<(\\S*?)[^>]*>.*?|<.*? />";

    /**
     * 这段代码是一个自定义的验证器方法，用于检查输入的字符串是否包含HTML标签。首先判断输入的字符串是否为空，如果为空则返回true，表示验证通过。如果不为空，则调用containsHtml方法来检查是否包含HTML标签，如果不包含HTML标签则返回true，表示验证通过；否则返回false，表示验证不通过。这个方法的作用是确保输入的字符串不包含HTML标签。
     * @param value
     * @param constraintValidatorContext
     * @return
     */
    @Override
    public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
        if (StringUtils.isBlank(value)) {
            return true;
        }
        return !containsHtml(value);
    }

    /**
     * 用于检查输入的字符串是否包含HTML标签
     * @param value
     * @return
     */
    public static boolean containsHtml(String value) {
        Pattern pattern = Pattern.compile(HTML_PATTERN);  // 通过Pattern.compile方法编译了一个正则表达式HTML_PATTERN，用于匹配HTML标签
        Matcher matcher = pattern.matcher(value);  // 。然后使用matcher方法创建一个Matcher对象，用于在输入的字符串value中查找匹配HTML_PATTERN（正则表达式）的部分
        return matcher.matches();  // 返回一个boolean值，表示输入的字符串是否完全匹配HTML_PATTERN。如果返回true，则表示输入的字符串包含HTML标签，否则不包含。
    }
}
